package com.community.demo.service.impl;

import com.community.demo.dao.BlogRepository;
import com.community.demo.domain.Blog;
import com.community.demo.domain.Goods;
import com.community.demo.service.IBlogService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.Predicate;
import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class BlogServiceImpl implements IBlogService {

    @Autowired
    private BlogRepository blogRepository;

    /**
     * 分页
     * @param searchParameters
     * @return
     */
    @Override
    @Transactional
    public Map getPage(final Map searchParameters){
        // 函数的返回值
        Map map = new HashMap();

        // 对 page 和 pageSize 的初始化
        int page = 0;
        int pageSize = 10;
        if(searchParameters!=null && searchParameters.size()>0 && searchParameters.get("page")!=null){
            page = Integer.parseInt(searchParameters.get("page").toString()) - 1;
        }
        if(searchParameters!=null && searchParameters.size()>0 && searchParameters.get("pageSize")!=null){
            pageSize = Integer.parseInt(searchParameters.get("pageSize").toString());
        }
        if(page<0){
            page = 0;
        }
        if(pageSize > 100){
            pageSize = 100;
        }

        // 处理sort,因为需要一个pageable
        PageRequest pageable;

        // 获取所有sort方式的map
        List<Map> orderMaps = (List<Map>) searchParameters.get("sort");

        List<Sort.Order> orders = new ArrayList<>();
        if(orderMaps!=null){
            for(Map order : orderMaps){
                String field = order.get("field").toString();
                if(field != null) {
                    continue;
                }
                if(!StringUtils.isEmpty(field)){
                    String dir = order.get("dir").toString();
                    if(dir.equalsIgnoreCase("DESC")){
                        orders.add(new Sort.Order(Sort.Direction.DESC, field));
                    }else{
                        orders.add(new Sort.Order(Sort.Direction.ASC, field));
                    }
                }
            }
        }

        // pageable的最终处理
        if(orders.size()>0){
            pageable = PageRequest.of(page, pageSize, Sort.by(orders));
        }else{
//            orders.add(new Order(Sort.Direction.ASC, "id"));
            Sort sort = Sort.by(Sort.Direction.ASC, "id");
            pageable = PageRequest.of(page, pageSize, sort);
        }

        // 可以理解为结果集
        Page<Blog> pageList;

        // 处理filter 因为需要一个spec
        Map filter = (Map) searchParameters.get("filter");
        if(filter!=null) {
            final List<Map> filters = (List<Map>) filter.get("filters");

            // 构造匿名内部类
            Specification<Blog> spec = (Specification<Blog>) (root, criteriaQuery, criteriaBuilder) -> {
                List<Predicate> predicates = new ArrayList<>();
                for (Map f : filters){
                    String field = f.get("field").toString().trim();
                    String value = f.get("value").toString().trim();
                    if(value!=null && value.length()>0){
                        predicates.add(criteriaBuilder.equal(root.get(field), value));
                    }
                }
                // 筛选出没有经过伪删除的
                predicates.add(criteriaBuilder.equal(root.get("flag"), 1));
                return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
            };
            pageList = blogRepository.findAll(spec, pageable);
        }else {
            Specification<Blog> spec = (Specification<Blog>) (root, criteriaQuery, criteriaBuilder) -> {
                List<Predicate> predicates = new ArrayList<>();
                predicates.add(criteriaBuilder.equal(root.get("flag"), 1));
                return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
            };
            pageList = blogRepository.findAll(spec, pageable);
        }

        map.put("total", pageList.getTotalElements());

        List<Blog> blogs = pageList.getContent();
        map.put("blogs", blogs);
        return map;
    }

    @Override
    public List<Blog> findAll() {
        return blogRepository.findAll();
    }

    @Override
    public void saveAndFlush(Blog blog) {
        blogRepository.saveAndFlush(blog);
    }

    @Override
    public void deleteById(long id) {
        Blog blog = blogRepository.findById(id).get();
        blog.setFlag(false);
        blogRepository.saveAndFlush(blog);
    }

    @Override
    public Blog getBlogById(long id) {
        return blogRepository.findById(id).get();
    }

}
